<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>parse_expression 函数流程图</title>
    <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
        mermaid.initialize({ 
            startOnLoad: true,
            // theme: 'dark',
            themeVariables: {
                fontSize: '16px',
                fontFamily: 'arial'
            }
        });
    </script>
    <style>
        body {
            background-color: #1e1e1e;
            color: #d4d4d4;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            padding: 20px;
            margin: 0;
        }
        .container {
            max-width: 1400px;
            margin: 0 auto;
        }
        h1 {
            color: #4ec9b0;
            border-bottom: 2px solid #4ec9b0;
            padding-bottom: 10px;
        }
        h2 {
            color: #569cd6;
            margin-top: 40px;
        }
        .mermaid {
            background-color: #252526;
            padding: 20px;
            border-radius: 8px;
            margin: 20px 0;
            overflow-x: auto;
        }
        .description {
            background-color: #2d2d30;
            padding: 15px;
            border-radius: 5px;
            margin: 20px 0;
            border-left: 4px solid #4ec9b0;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            background-color: #2d2d30;
        }
        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #404040;
        }
        th {
            background-color: #1e1e1e;
            color: #4ec9b0;
            font-weight: bold;
        }
        code {
            background-color: #1e1e1e;
            padding: 2px 6px;
            border-radius: 3px;
            color: #ce9178;
        }
        .highlight {
            color: #dcdcaa;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🔍 parse_expression 函数流程图分析</h1>
        
        <div class="description">
            <p><strong>文件位置：</strong> <code>src/parser/mod.rs:307-352</code></p>
            <p><strong>功能：</strong> 这是 Pratt 解析器的核心函数，用于解析表达式并处理运算符优先级。</p>
        </div>

        <h2>📊 主流程图</h2>
        <div class="mermaid">
flowchart TD
    Start([开始: parse_expression<br/>参数: precedence]) --> GetPrefix{获取前缀解析<br/>函数映射}
    
    GetPrefix -->|映射不存在| ReturnNone1[返回 None]
    GetPrefix -->|映射存在| LookupPrefix{查找当前 token 对应的<br/>前缀解析函数}
    
    LookupPrefix -->|未找到| Error[调用 no_prefix_parse_fn_error<br/>添加错误信息]
    Error --> ReturnNone2[返回 None]
    
    LookupPrefix -->|找到| CallPrefix[调用前缀解析函数<br/>获取左侧表达式 lf_exp]
    
    CallPrefix --> WhileCheck{检查循环条件:<br/>1. peek_token 不是分号<br/>2. precedence < peek_precedence}
    
    WhileCheck -->|条件不满足| ReturnExp[返回 lf_exp]
    
    WhileCheck -->|条件满足| LookupInfix{查找 peek_token 对应的<br/>中缀解析函数}
    
    LookupInfix -->|未找到| ReturnExp2[返回当前 lf_exp]
    
    LookupInfix -->|找到| NextToken[移动到下一个 token<br/>self.next_token]
    
    NextToken --> CallInfix[调用中缀解析函数<br/>传入当前 lf_exp 作为左侧]
    
    CallInfix --> UpdateExp[更新 lf_exp<br/>为新的表达式结果]
    
    UpdateExp --> WhileCheck
    
    ReturnExp --> End([结束])
    ReturnExp2 --> End
    ReturnNone1 --> End
    ReturnNone2 --> End
    
    style Start fill:#264f78,stroke:#4ec9b0,stroke-width:2px,color:#fff
    style End fill:#264f78,stroke:#4ec9b0,stroke-width:2px,color:#fff
    style Error fill:#5a1d1d,stroke:#f48771,stroke-width:2px,color:#fff
    style ReturnNone1 fill:#5a1d1d,stroke:#f48771,stroke-width:2px,color:#fff
    style ReturnNone2 fill:#5a1d1d,stroke:#f48771,stroke-width:2px,color:#fff
    style WhileCheck fill:#3c3c1e,stroke:#dcdcaa,stroke-width:2px,color:#fff
    style CallPrefix fill:#1e3a1e,stroke:#4ec9b0,stroke-width:2px,color:#fff
    style CallInfix fill:#1e3a1e,stroke:#4ec9b0,stroke-width:2px,color:#fff
        </div>

        <h2>📝 示例：解析表达式 <code>1 + 2 * 3</code></h2>
        <div class="description">
            <p>这个例子展示了如何通过优先级处理，正确地将表达式解析为 <code>1 + (2 * 3)</code> 而不是 <code>(1 + 2) * 3</code></p>
        </div>
        <div class="mermaid">
flowchart LR
    subgraph Step1 ["步骤1: 解析 1"]
        S1[precedence=LOWEST<br/>cur_token=1]
        S1 --> S1R[调用 parse_integer_literal<br/>返回 IntegerLiteral 1]
    end
    
    subgraph Step2 ["步骤2: 检查 +"]
        S2[peek_token=+<br/>LOWEST < SUM?<br/>✓ 是]
        S2 --> S2R[调用 parse_infix_expression<br/>left=1]
    end
    
    subgraph Step3 ["步骤3: 解析 2"]
        S3[precedence=SUM<br/>cur_token=2]
        S3 --> S3R[递归调用 parse_expression<br/>返回 IntegerLiteral 2]
    end
    
    subgraph Step4 ["步骤4: 检查 *"]
        S4[peek_token=*<br/>SUM < PRODUCT?<br/>✓ 是]
        S4 --> S4R[继续循环处理 *]
    end
    
    subgraph Step5 ["步骤5: 解析 3"]
        S5[precedence=PRODUCT<br/>cur_token=3]
        S5 --> S5R[返回 IntegerLiteral 3]
    end
    
    subgraph Result ["最终结果"]
        R["InfixExpression<br/>├─ left: 1<br/>├─ op: +<br/>└─ right: InfixExpression<br/>   ├─ left: 2<br/>   ├─ op: *<br/>   └─ right: 3"]
    end
    
    Step1 --> Step2
    Step2 --> Step3
    Step3 --> Step4
    Step4 --> Step5
    Step5 --> Result
    
    style Step1 fill:#1e3a1e,stroke:#4ec9b0,stroke-width:2px
    style Step2 fill:#264f78,stroke:#569cd6,stroke-width:2px
    style Step3 fill:#1e3a1e,stroke:#4ec9b0,stroke-width:2px
    style Step4 fill:#264f78,stroke:#569cd6,stroke-width:2px
    style Step5 fill:#1e3a1e,stroke:#4ec9b0,stroke-width:2px
    style Result fill:#3c1e1e,stroke:#ce9178,stroke-width:2px
        </div>

        <h2>📋 运算符优先级表</h2>
        <table>
            <thead>
                <tr>
                    <th>优先级名称</th>
                    <th>数值</th>
                    <th>运算符</th>
                    <th>说明</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td><code>LOWEST</code></td>
                    <td>1</td>
                    <td>-</td>
                    <td>最低优先级，用于开始解析</td>
                </tr>
                <tr>
                    <td><code>EQUALS</code></td>
                    <td>2</td>
                    <td><code>==</code>, <code>!=</code></td>
                    <td>相等性比较</td>
                </tr>
                <tr>
                    <td><code>LESSGREATER</code></td>
                    <td>3</td>
                    <td><code>&lt;</code>, <code>&gt;</code></td>
                    <td>大小比较</td>
                </tr>
                <tr>
                    <td><code>SUM</code></td>
                    <td>4</td>
                    <td><code>+</code>, <code>-</code></td>
                    <td>加减运算</td>
                </tr>
                <tr>
                    <td><code>PRODUCT</code></td>
                    <td>5</td>
                    <td><code>*</code>, <code>/</code></td>
                    <td>乘除运算</td>
                </tr>
                <tr>
                    <td><code>PREFIX</code></td>
                    <td>6</td>
                    <td><code>-X</code>, <code>!X</code></td>
                    <td>前缀运算符</td>
                </tr>
                <tr>
                    <td><code>CALL</code></td>
                    <td>7</td>
                    <td><code>()</code></td>
                    <td>函数调用（最高优先级）</td>
                </tr>
            </tbody>
        </table>

        <h2>🔑 核心机制详解</h2>
        
        <div class="description">
            <h3 class="highlight">1. Pratt 解析器原理</h3>
            <p>Pratt 解析器（也称为自顶向下运算符优先级解析器）通过两个关键概念处理表达式：</p>
            <ul>
                <li><strong>前缀函数 (prefix_parse_fns)</strong>：处理前缀运算符和操作数（如 <code>-5</code>, <code>!true</code>, 标识符, 数字等）</li>
                <li><strong>中缀函数 (infix_parse_fns)</strong>：处理中缀运算符（如 <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>）</li>
            </ul>
        </div>

        <div class="description">
            <h3 class="highlight">2. 优先级比较的关键</h3>
            <p>在 while 循环中，<code>precedence < self.peek_precedence()</code> 这个条件决定了：</p>
            <ul>
                <li>如果下一个运算符优先级<strong>更高</strong>，它会"吸引"右侧的操作数</li>
                <li>如果下一个运算符优先级<strong>更低或相等</strong>，当前表达式就完成了</li>
            </ul>
            <p><strong>示例：</strong>解析 <code>1 + 2 * 3</code> 时：</p>
            <ol>
                <li>解析到 <code>+</code>（SUM = 4）后，继续以 SUM 优先级解析右侧</li>
                <li>看到 <code>*</code>（PRODUCT = 5），因为 4 < 5，所以 <code>*</code> 会先"吸引" <code>2</code> 和 <code>3</code></li>
                <li>形成 <code>2 * 3</code> 子表达式，最后与 <code>1</code> 通过 <code>+</code> 连接</li>
            </ol>
        </div>

        <div class="description">
            <h3 class="highlight">3. 递归与循环的配合</h3>
            <ul>
                <li><strong>递归</strong>：处理嵌套的表达式（如括号、函数调用）</li>
                <li><strong>循环</strong>：处理相同优先级的左结合运算符（如 <code>1 + 2 + 3</code>）</li>
            </ul>
        </div>

        <h2>💡 为什么这样设计？</h2>
        <div class="description">
            <ol>
                <li><strong>简洁性</strong>：不需要为每个运算符编写单独的解析函数</li>
                <li><strong>可扩展性</strong>：添加新运算符只需注册函数和优先级</li>
                <li><strong>正确性</strong>：自动处理运算符优先级和结合性</li>
                <li><strong>高效性</strong>：单遍扫描即可完成解析</li>
            </ol>
        </div>

    </div>
</body>
</html>
